package net.dgg.rz.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Describe: json工具集
 * Created by yan.x on 2018/10/18 .
 **/
public final class JSONUtils {

    /**
     * JSON是否为空
     *
     * @param map 集合
     * @return 是否为空
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return null == map || map.isEmpty();
    }

    /**
     * JSON是否为非空
     *
     * @param map 集合
     * @return 是否为非空
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return null != map && false == map.isEmpty();
    }

    /*--------------------------[ build ]--------------------------*/

    public static JSONObject fastBuild() {
        return new JSONObject();
    }

    public static JSONObject fastBuild(String key, Object value) {
        JSONObject json = fastBuild();
        json.put(key, value);
        return json;
    }

    public static com.alibaba.fastjson.JSONArray fastArrayBuild() {
        return new com.alibaba.fastjson.JSONArray();
    }

    public static <T> T toJavaObject(String str, Class<T> clazz) {
        return TypeUtils.cast(JSONObject.parseObject(str), clazz, ParserConfig.getGlobalInstance());
    }

    public static <T> T toJavaObject(JSONObject obj, Class<T> clazz) {
        return TypeUtils.cast(obj, clazz, ParserConfig.getGlobalInstance());
    }


    public static JSONObject toJSONObject(String str) {
        return JSONObject.parseObject(str);
    }

    public static JSONObject toJSONObject(Object javaObject) {
        return (JSONObject) JSONObject.toJSON(javaObject);
    }
    /*--------------------------[ filter ]--------------------------*/

    /**
     * 过滤字段
     *
     * @param json   : 查询json
     * @param fields : 需要过滤的字段
     */
    public static void filterField(JSONObject json, String... fields) {
        if (null == json) {
            return;
        }
        if (json.containsKey("v")) {
            json.remove("v");
        }
        List<String> fileds = Arrays.asList(fields);
        Iterator<String> iterator = json.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            try {
                if (fileds.contains(key)) {
                    iterator.remove();
                }
            } catch (Exception e) {
                System.err.println(">>>> : 转换异常信息 " + key + " : " + json.get(key));
                e.printStackTrace();
            }
        }
    }

    /*-----------------------------[ toJSONString ]-----------------------------*/

    public static String toJSONString(Object obj) {
        return null == obj ? "{}" : JSONObject.toJSONString(obj);
    }

    public static String toJSONString(Object obj, SerializerFeature... features) {
        return null == obj ? "{}" : JSONObject.toJSONString(obj, features);
    }

    /*-----------------------------[ formatJSONString ]-----------------------------*/

    /**
     * <p>格式化对象并以json格式输出</p>
     *
     * @param obj : 预序列化对象
     * @return json格式的字符串
     */
    public static String formatJSONString(Object obj) {
        return formatJSONString(JSONObject.toJSONString(obj));
    }


    /**
     * 格式化对象并以json格式输出
     *
     * @param json
     * @return
     */
    public static String formatToJSONString(String json) {
        com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
        Object obj = null;
        try {
            obj = mapper.readValue(json, Object.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (com.fasterxml.jackson.core.JsonProcessingException e) {
            e.printStackTrace();
        }
        return "{}";
    }

    /**
     * <p>格式化对象并以json格式输出</p>
     *
     * @param json
     * @return json格式的字符串
     */
    public static String formatJSONString(String json) {
        if (null == json || "".equals(json) || "{}".equals(json)) {
            return "{}";
        }
        StringBuilder sb = new StringBuilder();
        char last = '\0';
        char current = '\0';
        int indent = 0;
        boolean isInQuotationMarks = false;
        for (int i = 0; i < json.length(); i++) {
            last = current;
            current = json.charAt(i);
            switch (current) {
                case '"':
                    if (last != '\\') {
                        isInQuotationMarks = !isInQuotationMarks;
                    }
                    sb.append(current);
                    break;

                case '{':
                case '[':
                    sb.append(current);
                    if (!isInQuotationMarks) {
                        sb.append('\n');
                        indent++;
                        addIndentBlank(sb, indent);
                    }
                    break;

                case '}':
                case ']':
                    if (!isInQuotationMarks) {
                        sb.append('\n');
                        indent--;
                        addIndentBlank(sb, indent);
                    }
                    sb.append(current);
                    break;

                case ',':
                    sb.append(current);
                    if (last != '\\' && !isInQuotationMarks) {
                        sb.append('\n');
                        addIndentBlank(sb, indent);
                    }
                    break;

                default:
                    sb.append(current);
            }
        }

        return sb.toString();
    }

    /**
     * 添加space
     *
     * @param sb
     * @param indent 缩进次数。
     */
    private static void addIndentBlank(StringBuilder sb, int indent) {
        for (int i = 0; i < indent; i++) {
            sb.append('\t');
        }
    }
}
